
#include "BSON.h"

#include "TestHeader.h"
#include "TestDriver.h"
#include "Logger.h"

using namespace BSON;

namespace 
{
}

void CConstructionTest::testDocument()
{
  CDocument* doc = CDocument::NewL();
  TS_ASSERT_EQUALS(doc->Count(), 0);
  delete doc;
}

void CConstructionTest::testArray()
{
  CArray* array = CArray::NewL();
  TS_ASSERT_EQUALS(array->Count(), 0);
  delete array;
}

void CConstructionTest::testString()
{
  _LIT(KStringValue, "string");
  for ( TElementType type = EDouble; type <= EInt64; type = static_cast<TElementType>(type + 1) )
  {
    if ( type == EUtf8String || type ==  EJavaScriptCode || type == ESymbol )
    {
      delete CString::NewL(KStringValue(), type);
      delete CString::NewL(KNullDesC(), type);
      continue;
    }
    TS_ASSERT_THROWS(CString::NewL(KStringValue(), type), KErrArgument);  
  }

  CString* string = CString::NewL(KStringValue(), EUtf8String);
  TS_ASSERT_EQUALS_DESCRIPTOR(string->Value(), KStringValue());
  delete string;
}

void CConstructionTest::testBinary()
{
  static const CBinary::TSubType validTypesData[] = {
                                    CBinary::EGeneric,
                                    CBinary::EFunction,
                                    CBinary::EOldBinary,
                                    CBinary::EUUID,
                                    CBinary::EMD5,
                                    CBinary::EUserDefined
  };
  DECLARE_ROM_ARRAY(validTypes, validTypesData, CBinary::TSubType);
  _LIT8(KBinaryValue, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\xff");

  for ( TUint8 i = 0; i <= validTypes.Length(); ++i )
  {
      delete CBinary::NewL(KBinaryValue(), validTypes[i]);
      delete CBinary::NewL(KNullDesC8(), validTypes[i]);
      TS_ASSERT_THROWS(CBinary::NewL(NULL, validTypes[i]), KErrArgument);
  }

  const CBinary::TSubType KInvalidSubtype = static_cast<CBinary::TSubType>(CBinary::EUserDefined+1);
  TS_ASSERT_THROWS(CBinary::NewL(NULL, KInvalidSubtype), KErrArgument);
  TS_ASSERT_THROWS(CBinary::NewL(KBinaryValue(), KInvalidSubtype), KErrArgument);

  CBinary* binary = CBinary::NewL(KBinaryValue(), CBinary::EGeneric);
  TS_ASSERT_EQUALS_DESCRIPTOR(binary->Value(), KBinaryValue());
  delete binary;
}

void CConstructionTest::TestNull()
{
  delete CNull::NewL();
}

void CConstructionTest::TestBool()
{
  CBoolean* boolean = CBoolean::NewL();
  TS_ASSERT_EQUALS(boolean->Value(), bool());
  delete boolean;

  boolean = CBoolean::NewL(true);
  TS_ASSERT_EQUALS(boolean->Value(), true);
  delete boolean;

  boolean = CBoolean::NewL(false);
  TS_ASSERT_EQUALS(boolean->Value(), false);
  delete boolean;
}

void CConstructionTest::TestInt32()
{
  CInt32* val = CInt32::NewL();
  TS_ASSERT_EQUALS(val->Value(), TInt32());
  delete val;
  
  val = CInt32::NewL(-1);
  TS_ASSERT_EQUALS(val->Value(), -1);
  delete val;

  val = CInt32::NewL(0);
  TS_ASSERT_EQUALS(val->Value(), 0);
  delete val;

  val = CInt32::NewL(~1);
  TS_ASSERT_EQUALS(val->Value(), ~1);
  delete val;
}

void CConstructionTest::TestInt64()
{
  CInt64* val = CInt64::NewL();
  TS_ASSERT_EQUALS(val->Value(), TInt64());
  delete val;

  val = CInt64::NewL(-1);
  TS_ASSERT_EQUALS(val->Value(), -1);
  delete val;

  val = CInt64::NewL(0);
  TS_ASSERT_EQUALS(val->Value(), 0);
  delete val;

  val = CInt64::NewL(~1);
  TS_ASSERT_EQUALS(val->Value(), ~1);
  delete val;
}

void CConstructionTest::TestDouble()
{
  CDouble* val = CDouble::NewL(TReal());
  TS_ASSERT_EQUALS(val->Value(), TReal());
  delete val;

  val = CDouble::NewL(TReal(0));
  TS_ASSERT_EQUALS(val->Value(), TReal(0));
  delete val;

  val = CDouble::NewL(TReal(-1));
  TS_ASSERT_EQUALS(val->Value(), TReal(-1));
  delete val;

  val = CDouble::NewL(TReal(1)/3);
  TS_ASSERT_EQUALS(val->Value(), TReal(1)/3);
  delete val;
}

void CConstructionTest::TestUtcDateTime()
{
  CUtcDateTime* val = CUtcDateTime::NewL();
  TS_ASSERT_EQUALS(val->Value(), TTime());
  delete val;

  val = CUtcDateTime::NewL(Time::MinTTime());
  TS_ASSERT_EQUALS(val->Value(), Time::MinTTime());
  delete val;

  val = CUtcDateTime::NewL(Time::MaxTTime());
  TS_ASSERT_EQUALS(val->Value(), Time::MaxTTime());
  delete val;

  val = CUtcDateTime::NewL(Time::NullTTime());
  TS_ASSERT_EQUALS(val->Value(), Time::NullTTime());
  delete val;

  TTime time;
  time.UniversalTime();
  val = CUtcDateTime::NewL(time);
  TS_ASSERT_EQUALS(val->Value(), time);
  delete val;
}

